package com.example.javacore.listtree;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson2.JSON;
import lombok.Data;

import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author tiger
 */
@Data
public class Area {
    private String code;
    private String parentCode;
    private String parentName;
    private String areaName;
    private Integer level;
    private List<Area> childrenList;

    /**
     * @param level    树的层级
     * @param totalNum 树的总节点数
     */
    public static List<Area> initRandomTree(int level, int totalNum) {
        Date start = new Date();
        List<Area> allList = new ArrayList<>(totalNum);
        for (int i = 0; i < level; i++) {
            Area area = new Area();
            area.setCode(String.valueOf(i));
            area.setParentCode(String.valueOf(i - 1));
            area.setAreaName("节点" + i);
            allList.add(area);
        }
        String id = "id";
        for (int i = 0; i < totalNum; i++) {
            Area area = new Area();
            area.setCode(id + i);
            area.setParentCode(String.valueOf(RandomUtil.randomInt(0, level)));
            allList.add(area);
        }
        System.out.println("生成随机树结构用时:" + DateUtil.betweenMs(start, new Date()));
        return allList;
    }

    /**
     * 输出结果集
     */
    public static void output(List<Area> result) {
        for (Area area : result) {
            StringBuilder space = new StringBuilder();
            for (int i = 0; i < area.getLevel(); i++) {
                space.append(".");
            }
            String node = space + area.getCode() + "[" + area.getParentCode() + "]" + area.getLevel();
            System.out.println(node);
        }
    }

    /**
     * 初始化默认树结构
     */
    public static List<Area> initArea() {
        List<Area> allList;
        String init = "[" +
                "{\"code\":\"beijing\",\"parentCode\":\"-1\",\"areaName\":'北京'}," +
                "{\"code\":\"shunYi\",\"parentCode\":\"beijing\",\"areaName\":'顺义'}," +
                "{\"code\":\"heShan\",\"parentCode\":\"heBi\",\"areaName\":'鹤山区'}," +
                "{\"code\":\"heBi\",\"parentCode\":\"heNan\",\"areaName\":'鹤壁'}," +
                "{\"code\":\"guXian\",\"parentCode\":\"yanShi\",\"areaName\":'顾县'}," +
                "{\"code\":\"luoLong\",\"parentCode\":\"luoYang\",\"areaName\":'洛龙区'}," +
                "{\"code\":\"kouDian\",\"parentCode\":\"luoLong\",\"areaName\":'寇店镇'}," +
                "{\"code\":\"yanShi\",\"parentCode\":\"luoYang\",\"areaName\":'偃师'}," +
                "{\"code\":\"daiKou\",\"parentCode\":\"yanShi\",\"areaName\":'大口'}," +
                "{\"code\":\"haiDian\",\"parentCode\":\"beijing\",\"areaName\":'海淀'}," +
                "{\"code\":\"luoYang\",\"parentCode\":\"heNan\",\"areaName\":'洛阳'}," +
                "{\"code\":\"heNan\",\"parentCode\":\"-1\",\"areaName\":'河南'}," +
                "{\"code\":\"tianjin\",\"parentCode\":\"-1\",\"areaName\":'天津'}," +
                "]";
        allList = JSON.parseArray(init, Area.class);
        return allList;
    }

    /**
     * 递归设置树子节点,并设置权限
     *
     * @param node    节点
     * @param allList 所有节点列表
     */
    public static void recursionSetChildTreeList(Area node, List<Area> allList, List<Area> result) {
        //得到子节点列表
        List<Area> childList = new LinkedList<>();
        for (Area n : allList) {
            if (n != null && n.getParentCode() != null && n.getParentCode().equals(node.getCode())) {
                //设置子节点属性
                n.setLevel(node.getLevel() + 1);
                n.setParentName(node.getAreaName());

                //添加子节点
                childList.add(n);
            }
        }
        //设置所有的子节点
        node.setChildrenList(childList);

        for (Area tChild : childList) {
            if (allList.stream().anyMatch(item -> item.getParentCode().equals(tChild.getCode()))) {
                //有子节点,继续递归获取子节点
                result.add(tChild);
                recursionSetChildTreeList(tChild, allList, result);
            } else {
                result.add(tChild);
            }
        }

    }

    /**
     * 根据无序集合生成树形结构
     *
     * @param allList 序集合
     * @return 树形结构
     */
    public static List<Area> generateTreeStructure(List<Area> allList) {
        //获取一级节点
        List<Area> firstLevelNode = allList.stream().filter(n -> "-1".equals(n.getParentCode())).collect(Collectors.toList());
        List<Area> result = new LinkedList<>();
        for (Area tree : firstLevelNode) {
            //设置一级节点属性
            tree.setLevel(0);

            //一级节点加入结果集
            result.add(tree);
            //递归一级节点
            recursionSetChildTreeList(tree, allList, result);
        }
        return result;
    }

    /**
     * 递归遍历
     */
    public static List<Area> loopTraversal(List<Area> allList) {
        Date start = new Date();
        List<Area> firstLevelNode = allList.stream().filter(n -> "-1".equals(n.getParentCode())).collect(Collectors.toList());
        firstLevelNode.forEach(n -> n.setLevel(0));
        System.out.println("查找一级节点用时毫秒:" + DateUtil.betweenMs(start, new Date()));
        List<Area> nodePoint = firstLevelNode;
        List<Area> tmp;
        boolean hasChildNode = true;
        int level = 0;
        while (hasChildNode) {
            System.out.println("层级:" + level++);
            hasChildNode = false;
            tmp = new ArrayList<>();
            for (Area p : nodePoint) {
                for (Area area : allList) {
                    if (area.getParentCode().equals(p.getCode())) {
                        hasChildNode = true;
                        if (p.childrenList == null) {
                            p.childrenList = new ArrayList<>();
                        }
                        p.childrenList.add(area);
                        tmp.add(area);
                    }
                }
            }
            nodePoint = tmp;
        }
        return firstLevelNode;
    }

}
